/*
 * @author qianli
 * @date 2015/7/29
 * @brief Linux的每个进程只有一个闹钟这里实现的是一个进程可以有多个闹钟，调用多个函数
 *        我将原来的代码修改成函数指针的形式。形成调用函数。
 */

#include <string.h>
#include <stdio.h>
#include <signal.h>
#include <sys/types.h>
#include <stdlib.h>

#define N 100  //设置最大的定时器个数
int i = 0, t = 0; //i代表定时器的个数；t表示时间，逐秒递增。

typedef void (*func)(void);

void print1(void)
{
    printf("------------Timer 1: --Hello Aillo!\n"); 
}

void print2(void)
{
    printf("------------Timer 2: --Hello Jackie!\n"); 
}

void print3(void)
{
    printf("------------Timer 3: --Hello PiPi!\n"); 
}

struct Timer //Timer结构体，用来保存一个定时器的信息
{
    int total_time; //每隔total_time秒
    int left_time; //还剩left_time秒
    func fun; //该定时器超时，要执行的代码的标志
}myTimer[N]; //定义Timer类型的数组，用来保存所有定时器

void setTimer(int t, func f) //新建一个定时器
{
    struct Timer a;
    a.total_time = t;
    a.left_time = t;
    a.fun = f;
    myTimer[i++] = a;
}

void timeout() //判断定时器是否超时，以及超时时要执行的动作
{
    alarm(1);
    printf("Time: %d\n", t++);
    int j;
    for (j = 0; j < i; j++)
    {
        if (myTimer[j].left_time != 0)
            --myTimer[j].left_time;
        else
        {

            myTimer[j].fun();
            /*
            switch(myTimer[j].func)
            {
                case 1:
                    printf("------------Timer 1: --Hello Aillo!\n"); 
                    break;
                case 2:
                    printf("------------Timer 2: --Hello Jackie!\n"); 
                    break;
                case 3:
                    printf("------------Timer 3: --Hello PiPi!\n"); 
                    break;
                default:
                    printf("------------Timer default: --Hello World!!!\n");
            }
            */
            myTimer[j].left_time = myTimer[j].total_time; //循环计时
        }
    }
}

int main(int argc, char** argv)
{
    setTimer(3, print1);
    setTimer(4, print2);
    setTimer(5, print3);

    signal(SIGALRM, timeout); //接到SIGALRM信号，则执行timeout函数
    //timeout();
    alarm(1);

    while (1)
    {
        //sleep(1);
        //kill(getpid(), SIGALRM);
        pause();
    }

    exit(0);
}
